import TileLayer from 'ol/layer/Tile'
import WMTS from 'ol/source/WMTS' // eslint-disable-line
import TileArcGISRest from 'ol/source/TileArcGISRest'
import VectorSource from 'ol/source/Vector'
import ImageStatic from 'ol/source/ImageStatic'
import VectorLayer from 'ol/layer/Vector'
import ImageLayer from 'ol/layer/Image'
import LayerGroup from 'ol/layer/Group'
import Cluster from 'ol/source/Cluster'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { Fill, Stroke, Style, Circle as circleStyle } from 'ol/style'
import { fromLonLat, get as getProjection } from 'ol/proj'
import { getTopLeft, getWidth } from 'ol/extent'
import Feature from 'ol/Feature'
import Polygon from 'ol/geom/Polygon'
import Point from 'ol/geom/Point'
import GeoJSON from 'ol/format/GeoJSON'
import Icon from 'ol/style/Icon'
import Text from 'ol/style/Text'
import Overlay from 'ol/Overlay'
import { fromExtent } from 'ol/geom/Polygon'
import { LinearRing, MultiPolygon } from 'ol/geom'
import { Select } from 'ol/interaction'
import { click } from 'ol/events/condition'
import { getDistance } from 'ol/sphere'
import { getVectorContext } from 'ol/render'

function Layer(map) {
    this.map = map
}
/**
 * @description: 创建一个样式
 * @param {*} styleObj 样式对象
 * @returns 样式对象
 */
let styleFunction = function (styleObj) {
    const style = new Style({
        stroke: new Stroke({
            color: styleObj.strokeColor || '#FFFFFF',
            width: styleObj.strokeWidth || 1,
        }),
        fill: new Fill({
            color: styleObj.fillColor || 'rgba(255,255,255,0.5)',
        }),
    })
    return style
}
/**
 * @description: 创建一个图层组
 * @param {*} LayerGroupName 图层组名称
 * @param {*} zIndex 图层顺序
 * @param {*} layers 图层数组 []
 * @return {*} layerGroup
 */
Layer.prototype.createGroup = function (layerGroupName, zIndex, layers) {
    let layerGroup = new LayerGroup({
        layers: layers,
        zIndex: zIndex || 0,
    })
    layerGroup.set('layerName', layerGroupName || '图层组')
    return layerGroup
}
/**
 * @description 切换基础底图
 * @param {String} type - 底图类型，必传
 * @returns {}
 */
Layer.prototype.changeBaseMap = function (type = 'vector') {
    const LayerObj = {
        vector: '矢量图层组',
        image: '影像图层组',
        terrain: '地形图层组',
    }
    for (let key in LayerObj) {
        const layer = this.getLayerByName(LayerObj[key])
        layer.setVisible(key === type)
    }
}
/**
 * @description: 初始化图层，影像与矢量
 * @param {*} geom geometry对象
 */
Layer.prototype.initLayer = function (geom) {
    //------------添加影像 全国影像
    const img = this.getTianDiTuWmtsLayerByParam('天地图影像', 'img', 'img')
    const cia = this.getTianDiTuWmtsLayerByParam('天地图影像注记', 'cia', 'cia')
    const imgLayerGroup = this.createGroup('影像图层组', 1, [img, cia])
    imgLayerGroup.setVisible(false)
    this.map.addLayer(imgLayerGroup) //添加影像

    //------------添加矢量 全国矢量
    const vec = this.getTianDiTuWmtsLayerByParam('天地图矢量', 'vec', 'vec')
    const cva = this.getTianDiTuWmtsLayerByParam('天地图矢量注记', 'cva', 'cva')
    const vecLayerGroup = this.createGroup('矢量图层组', 2, [vec, cva])
    // vecLayerGroup.setVisible(false)
    this.map.addLayer(vecLayerGroup) //添加矢量

    //------------添加 全国地形
    const ter = this.getTianDiTuWmtsLayerByParam('天地图地形', 'ter', 'ter')
    const cta = this.getTianDiTuWmtsLayerByParam('天地图地形注记', 'cta', 'cta')
    const terLayerGroup = this.createGroup('地形图层组', 2, [ter, cta])
    terLayerGroup.setVisible(false)
    this.map.addLayer(terLayerGroup) //添加地形

    //-------------添加地图遮罩，并将地图放大到geom范围
    const boundaryLayer = this.createMaskLayer('行政区域遮罩图层') //zindex为10
    boundaryLayer.getSource().clear()
    let extent = geom.getExtent()
    this.fitExtentPaddingLayout(extent)
    this.addPolygonHoles(boundaryLayer, geom, {
        strokeColor: 'white',
        strokeWidth: 2,
        fillColor: 'rgba(0,0,0,0.4)',
    })
    return {
        layer: this.map.getLayers().getArray(),
        extent: extent,
    }
}

/**
 * @description: 叠加WMTS
 * @param {string} layerName 图层名称
 * @param {string} url 图层路径
 * @param {object} params 参数
 * @return {TileLayer} 图层对象
 */
Layer.prototype.getTianDiTuWmtsLayerByParam = function (layerName, url, type) {
    const token = 'fe40e8bfa4d16f7a68afafe70ad0483e'
    let m = parseInt(Math.random() * 8) //0-7随机选择
    const img =
        'http://t' +
        m +
        '.tianditu.gov.cn/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&tk=' //影像底图
    const cia =
        'http://t' +
        m +
        '.tianditu.gov.cn/cia_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&tk=' //影像注记
    const vec =
        'http://t' +
        m +
        '.tianditu.gov.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&tk=' //矢量底图
    const cva =
        'http://t' +
        m +
        '.tianditu.gov.cn/cva_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&tk=' //矢量注记
    const ter =
        'http://t' +
        m +
        '.tianditu.gov.cn/ter_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=tre&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&tk=' //地形底图
    const cta =
        'http://t' +
        m +
        '.tianditu.gov.cn/cta_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&tk=' //地形标注
    if (!url) return null
    url = decodeURIComponent(url)
    const projection = getProjection('EPSG:4326')
    const projectionExtent = projection.getExtent()
    const size = getWidth(projectionExtent) / 256
    const resolutions1 = new Array(19)
    const resolutions = new Array(19)
    const matrixIds = new Array(19)
    for (let z = 0; z < 20; ++z) {
        //1.40625
        resolutions1[z] = size / Math.pow(2, z) //天地图经纬 度底图的计算参数
        resolutions[z] = 1.40625285 / Math.pow(2, z) //苍穹 底图计算参数（可能需要修改，根据点位偏移自己去调整）
        matrixIds[z] = z
    }
    let source = new WMTS({
        name: layerName,
        url: url,
        layer: type,
        style: 'default',
        matrixSet: 'c',
        format: 'tiles',
        wrapX: true,
        tileGrid: new WMTSTileGrid({
            origin: getTopLeft(projectionExtent), //resolutions: res.slice(0, 15),
            resolutions: resolutions,
            matrixIds: matrixIds,
        }),
    })
    source.setTileUrlFunction(function (data) {
        let tilematrix = data[0]
        let tilecol = data[1]
        let tilerow = data[2]
        let baseUrl = ''
        if (type == 'img') baseUrl = img
        if (type == 'cia') baseUrl = cia
        if (type == 'vec') baseUrl = vec
        if (type == 'cva') baseUrl = cva
        if (type == 'ter') baseUrl = ter
        if (type == 'cta') baseUrl = cta
        return (
            baseUrl +
            token +
            `&TILEMATRIX=${tilematrix}&TILECOL=${tilecol}&TILEROW=${tilerow}`
        )
    })

    let layer = new TileLayer({
        source: source,
    })
    // this.map.addLayer(layer);
    return layer
}

/**
 * @description: 添加一个矢量遮罩图层
 * @param {*} layerName 图层名
 * @param {*} zIndex 图层
 * @return {*} vectorLayer
 */
Layer.prototype.createMaskLayer = function (layerName, zIndex) {
    let vectorLayer = new VectorLayer({
        source: new VectorSource(),
        zIndex: zIndex || 10,
        declutter: false, //防止标注文字重复标注
        style: new Style({
            fill: new Fill({
                color: 'rgba( 255, 255, 255, 0.7)',
            }),
            stroke: new Stroke({
                color: '#f4b49f',
                width: 3,
            }),
        }),
    })
    vectorLayer.set('layerName', layerName || '遮罩图层')
    this.map.addLayer(vectorLayer)
    return vectorLayer
}
/**
 * @description: 地图放大到某个区域
 * @param {*} extent 范围
 * @param {*} paddingList 边距
 * @return {*}
 */
Layer.prototype.fitExtentPadding = function (
    extent,
    paddingList,
    duration,
    maxZoom,
) {
    this.map.getView().fit(extent, {
        duration: duration || 0, // 动画持续时间（毫秒）
        padding: paddingList || [0, 0, 0, 0], // 可根据需要调整填充值
        maxZoom: maxZoom,
    })
}

//[100, 0, 20, 0]相对于布局的padding
Layer.prototype.fitExtentPaddingLayout = function (extent, duration) {
    this.fitExtentPadding(extent, [150, 150, 150, 150], duration)
}
/**
 * @description: 行政区遮罩（带洞多边形）
 * @param {*} layer 遮罩图层
 * @param {*} holeGeom 行政区多边形
 * @param {*} styleObj 遮罩样式
 * @return {*}
 */
Layer.prototype.addPolygonHoles = function (layer, holeGeom, styleObj = {}) {
    let extent = [-180, -90, 180, 90]
    let polygonRing = fromExtent(extent) //从范围创建多边形
    let coords = holeGeom.getCoordinates() //获取此几何的坐标数组。该数组具有用于多边形的GeoJSON坐标数组的结构
    if (holeGeom instanceof MultiPolygon)
        coords.forEach((coord) => {
            let linearRing = new LinearRing(coord[0])
            polygonRing.appendLinearRing(linearRing) //将传递的线环添加到这个多边形
        })
    else {
        let linearRing = new LinearRing(coords[0])
        polygonRing.appendLinearRing(linearRing) //将传递的线环添加到这个多边形
    }
    let feature = new Feature({ geometry: polygonRing })
    feature.setStyle(styleFunction(styleObj))
    layer.getSource().addFeature(feature)
}
/**
 * @description: 获取所有的图层
 * @return {*} 对应图层对象
 */
Layer.prototype.getAllLayers = function () {
    let layerArr = this.map.getLayers().getArray()
    return layerArr
}
/**
 * @description: 根据图层名获取图层
 * @param {string} layerName 图层名称
 * @return {*} 对应图层对象
 */
Layer.prototype.getLayerByName = function (layerName) {
    let layerArr = this.getAllLayers()
    for (let k = 0; k < layerArr.length; k++) {
        if (
            layerArr[k].values_.layerName == layerName ||
            layerArr[k].layerName == layerName
        ) {
            return layerArr[k]
        }
    }
}
/**
 * @description: 添加自定义图层
 */
Layer.prototype.addLayers = function (layerName, zIndex) {
    //------------添加点图层
    const addVectorLayers = new VectorLayer({
        source: new VectorSource(),
        zIndex: zIndex,
    })
    addVectorLayers.set('layerName', layerName)
    this.map.addLayer(addVectorLayers)
    return this.map.getLayers().getArray()
}
/**
 * @description : 添加点---普通
 *
 * @param {Feature} point - 要添加的点特征
 * @param {string} LayerName - 图层的名称
 * */
Layer.prototype.addGenralPoint = function (point, LayerName) {
    console.log(point, 'point')
    const source = new VectorSource({
        features: point,
    })
    let layer = this.getLayerByName(LayerName)
    layer.setSource(source)
}
/**
 * 设置指定图层的图标样式
 * @param {string} layerName - 图层名称
 * @param {string} iconPath - 图标文件路径
 * @param {number} [scale=1] - 图标缩放比例
 * @returns {void}
 */
Layer.prototype.setLayerIconStyle = function (layerName, iconPath, scale = 1) {
    // 获取图层
    const layer = this.getLayerByName(layerName)
    if (!layer) {
        console.warn(`图层 "${layerName}" 未找到`)
        return
    }
    console.log(iconPath, 'iconPath')
    // 创建样式函数
    const styleFunc = new Style({
        image: new Icon({
            src: iconPath,
            scale: scale,
            anchor: [0.5, 1], // 图标底部对准点位置
        }),
    })

    // 设置所有要素的样式
    const features = layer.getSource().getFeatures()
    features.forEach((feature) => {
        feature.setStyle(styleFunc)
    })
}

const getImage = (type, imageType, grade) => {
    console.log('imageType:', imageType)
    const webUrl = 'https://env-00jxt6hwsqjo.normal.cloudstatic.cn/lhmap/map/'
    let imageUrl = ''
    switch (type) {
        case 'monitoring':
            switch (imageType) {
                case '1':
                    imageUrl = 'hong.svg'
                    break
                case '2':
                    imageUrl = 'cheng.svg'
                    break
                case '3':
                    imageUrl = 'huang.svg'
                    break
                case '4':
                    imageUrl = 'lan.svg'
                    break
                default:
                    imageUrl = 'lv.svg'
                    break
            }
            break
        case 'hiddenPoint':
            switch (imageType) {
                case '滑坡':
                    switch (grade) {
                        case '低':
                            imageUrl = 'huapo2.svg'
                            break
                        case '中':
                            imageUrl = 'huapo3.svg'
                            break
                        case '高':
                            imageUrl = 'huapo4.svg'
                            break
                        case '极高':
                            imageUrl = 'huapo5.svg'
                            break
                        default:
                            imageUrl = 'huapo1.svg'
                            break
                    }
                    break
                case '泥石流':
                    switch (grade) {
                        case '低':
                            imageUrl = 'nishiliu2.svg'
                            break
                        case '中':
                            imageUrl = 'nishiliu3.svg'
                            break
                        case '高':
                            imageUrl = 'nishiliu4.svg'
                            break
                        case '极高':
                            imageUrl = 'nishiliu5.svg'
                            break
                        default:
                            imageUrl = 'nishiliu1.svg'
                            break
                    }
                    break
                case '采空塌陷':
                    imageUrl = 'yanrongtaxian.svg'
                    break
                case '崩塌':
                    switch (grade) {
                        case '低':
                            imageUrl = 'bengta2.svg'
                            break
                        case '中':
                            imageUrl = 'bengta3.svg'
                            break
                        case '高':
                            imageUrl = 'bengta4.svg'
                            break
                        case '极高':
                            imageUrl = 'bengta5.svg'
                            break
                        default:
                            imageUrl = 'bengta1.svg'
                            break
                    }
                    break
                case '地裂缝':
                    switch (grade) {
                        case '低':
                            imageUrl = 'dilie2.svg'
                            break
                        case '中':
                            imageUrl = 'dilie3.svg'
                            break
                        case '高':
                            imageUrl = 'dilie4.svg'
                            break
                        case '极高':
                            imageUrl = 'dilie5.svg'
                            break
                        default:
                            imageUrl = 'dilie1.svg'
                            break
                    }
                    break
                case '地面沉降':
                    switch (grade) {
                        case '低':
                            imageUrl = 'chenjiang2.svg'
                            break
                        case '中':
                            imageUrl = 'chenjiang3.svg'
                            break
                        case '高':
                            imageUrl = 'chenjiang4.svg'
                            break
                        case '极高':
                            imageUrl = 'chenjiang5.svg'
                            break
                        default:
                            imageUrl = 'chenjiang1.svg'
                            break
                    }
                    break
                case '地面塌陷':
                    switch (grade) {
                        case '低':
                            imageUrl = 'taxian2.svg'
                            break
                        case '中':
                            imageUrl = 'taxian3.svg'
                            break
                        case '高':
                            imageUrl = 'taxian4.svg'
                            break
                        case '极高':
                            imageUrl = 'taxian5.svg'
                            break
                        default:
                            imageUrl = 'taxian1.svg'
                            break
                    }
                    break
                default:
                    switch (grade) {
                        case '低':
                            imageUrl = 'qita2.svg'
                            break
                        case '中':
                            imageUrl = 'qita3.svg'
                            break
                        case '高':
                            imageUrl = 'qita4.svg'
                            break
                        case '极高':
                            imageUrl = 'qita5.svg'
                            break
                        default:
                            imageUrl = 'qita1.svg'
                            break
                    }
                    break
            }
            break
        case 'qiepojianfang':
            switch (imageType) {
                case '待定':
                    imageUrl = 'qiepojianfang1.svg'
                    break
                case '低':
                    imageUrl = 'qiepojianfang2.svg'
                    break
                case '中':
                    imageUrl = 'qiepojianfang3.svg'
                    break
                case '高':
                    imageUrl = 'qiepojianfang4.svg'
                    break
                case '极高':
                    imageUrl = 'qiepojianfang5.svg'
                    break
            }
            break
        case 'quickpoint':
            imageUrl = 'suibaodian.svg'
            break
        case 'xiangmu':
            imageUrl = 'xiangmu.svg'
            break
    }
    return webUrl + imageUrl
}
/**
 * @description: 添加监测点
 * @param {*} points points点集
 */
Layer.prototype.addJcdPoint = function (points) {
    const layer = this.getLayerByName('监测点')
    // 懒加载图标样式缓存：key = 图标编码，value = 对应的 Style
    const iconStyleCache = {}

    // 样式函数：根据等级和 zoom 动态返回 style 或 null
    const styleFunc = (feature, resolution) => {
        const iconKey = feature.get('warnlevel')
        if (!iconStyleCache[iconKey]) {
            iconStyleCache[iconKey] = new Style({
                image: new Icon({
                    src: getImage('monitoring', iconKey),
                    scale: 0.7,
                }),
            })
        }
        return iconStyleCache[iconKey]
    }

    // 1. 设置图层样式函数
    layer.setStyle(styleFunc)
    // 2. 一次性清空并添加所有点
    const source = layer.getSource()
    source.clear()
    source.addFeatures(points)
}

/**
 * @description : 向图层中添加隐患点，并根据险情等级和地图缩放级别动态调整显示的隐患点。
 *
 * @param {Feature} points - 包含隐患点特征的数组，每个特征包含险情等级和样式信息。
 */
Layer.prototype.addYhdPoint = function (points) {
    // 获取图层
    const layer = this.getLayerByName('隐患点')
    // 懒加载图标样式缓存：key = 图标编码，value = 对应的 Style
    const iconStyleCache = {}

    const styleFunc = (feature, resolution) => {
        // 拿到图标编码，根据 zhaa11a024 生成或复用 Style
        const iconKey = feature.get('disastertype')
        const grade = feature.get('grade')
        if (!iconStyleCache[iconKey]) {
            iconStyleCache[iconKey] = new Style({
                image: new Icon({
                    src: getImage('hiddenPoint', iconKey, grade),
                    scale: 0.7,
                }),
            })
        }
        return iconStyleCache[iconKey]
    }
    // 1. 设置图层样式函数
    layer.setStyle(styleFunc)
    // 2. 一次性清空并添加所有点
    const source = layer.getSource()
    source.clear()
    source.addFeatures(points)
}

/**
 * @description : 向图层中添加切坡建房，
 * @param {Feature} points - 包含切坡建房特征的数组，每个特征包含风险等级和样式信息。
 */
Layer.prototype.addQpjfPoint = function (points) {
    const layer = this.getLayerByName('切坡建房')
    // 懒加载图标样式缓存：key = 图标编码，value = 对应的 Style
    const iconStyleCache = {}

    // 样式函数：根据等级和 zoom 动态返回 style 或 null
    const styleFunc = (feature, resolution) => {
        const iconKey = feature.get('grade')
        if (!iconStyleCache[iconKey]) {
            iconStyleCache[iconKey] = new Style({
                image: new Icon({
                    src: getImage('qiepojianfang', iconKey),
                    scale: 0.5,
                }),
            })
        }
        return iconStyleCache[iconKey]
    }
    // 1. 设置图层样式函数
    layer.setStyle(styleFunc)
    // 2. 一次性清空并添加所有点
    const source = layer.getSource()
    source.clear()
    source.addFeatures(points)
}
let otherLayer = null
/**
 * @description : 添加其他点
 * @param {Feature} points - 地图，
 * @param {string} name - 图层名称，
 * @param {string} obj - 点数据，
 */
Layer.prototype.addOtherPoint = function (points, name, obj) {
    if (otherLayer) {
        otherLayer.getSource().clear()
    }
    otherLayer = this.getLayerByName(name)
    // let n = '0'
    // switch (obj.type) {
    //   case "monitoring":
    //     switch (obj.data.level) {
    //       case "黄色预警":
    //         n = '3'
    //         break;
    //       case "橙色预警":
    //         n = '2'
    //         break;
    //       case "红色预警":
    //         n = '1'
    //         break;
    //       case "蓝色预警":
    //         n = '4'
    //         break;
    //     }
    //     break;
    //   case "hiddenPoint":
    //     n = obj.data.mold
    //     break;
    //   case "qiepojianfang":
    //     n = obj.data.riskLevel
    //     break;
    // }
    // 1. 设置图层样式函数
    otherLayer.setStyle(
        new Style({
            image: new Icon({
                src: getImage(obj.type),
                scale: 0.7,
            }),
        }),
    )
    // 2. 一次性清空并添加所有点
    const source = otherLayer.getSource()
    source.clear()
    source.addFeatures(points)
}
//添加风险区多边形
Layer.prototype.addFxqPolygon = function (features) {
    const layer = this.getLayerByName('风险区')
    // 样式函数：根据等级和 zoom 动态返回 style 或 null
    const styleFunc = (feature, resolution) => {
        return new Style({
            fill: new Fill({
                color: 'rgba(255, 165, 0, .2)',
            }),
            stroke: new Stroke({
                color: '#FFA500', // 边框
                width: 1, // 边框宽度
            }),
        })
    }
    // 1. 设置图层样式函数
    layer.setStyle(styleFunc)
    // 2. 一次性清空并添加所有点
    const source = layer.getSource()
    source.clear()
    source.addFeatures(features)
}
//添加聚合图层
Layer.prototype.addAggregateLayer = function (data) {
    const layer = this.getLayerByName('聚合图层')
    console.log('layer:', layer)

    // 创建点要素
    const feature = new Feature({
        geometry: new Point([data.x, data.y]),
        name: data.name,
        countvalue: data.countvalue,
    })

    // 创建聚合源
    const clusterSource = new Cluster({
        source: new VectorSource({
            features: [feature],
        }),
        distance: 40,
    })

    // 使用图片背景
    const style = new Style({
        image: new Icon({
            src: 'https://dzfz.hnzrzy.cn/monitors/juhex.svg',
            scale: 1.5,
            anchor: [0.5, 0.5],
        }),
        text: new Text({
            text: data.name + '\n' + data.countvalue,
            fill: new Fill({
                color: '#fff',
            }),
        }),
    })

    layer.setStyle(style)
    layer.setSource(clusterSource)

    // 添加地图事件监听，在缩放或移动时隐藏聚合图层
    const hideAggregateLayer = () => {
        if (layer) {
            this.map.removeLayer(layer)
        }
        // 移除事件监听
        this.map.un('moveend', hideAggregateLayer)
        this.map.un('zoomend', hideAggregateLayer)
    }

    // 监听地图移动和缩放事件
    this.map.on('moveend', hideAggregateLayer)
    this.map.on('zoomend', hideAggregateLayer)
}
export default Layer
